﻿// -----------------------------------------------------------------------
// <copyright file="Library_Legacy.cs" company="G.W. van der Vegt">
// SharpForth is inspired by JonesForthInC v1.48 and bb4wForth.
// </copyright>
// -----------------------------------------------------------------------
namespace SharpForth
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;

    /// <summary>
    /// This class contains the definitions of some additional pure Forth Words.
    /// </summary>
    public static partial class Library
    {
        #region Fields

        /// <summary>
        /// 
        /// </summary>
        [WordName("DIGIT")]
        [WordSet(WordSets.LEGACY)]
        [Depends("(")]
        [Depends("SWAP")]
        [Depends("DUP")]
        [Depends("0<")]
        [Depends("IF")]
        [Depends("DROP")]
        [Depends("FALSE")]
        [Depends("EXIT")]
        [Depends("THEN")]
        [Depends(">")]
        [Depends("-")]
        [Depends("TUCK")]
        [Depends("<=")]
        [Depends("TRUE")]
        [Syntax("( char base -- u valid )")]
        internal static String DIGIT = 
        ": DIGIT ( char base -- u valid )\n" +
        "  SWAP 48 -\n" +
        "  DUP 0< IF DROP FALSE EXIT THEN\n" +
        "  DUP 16 > IF 7 - THEN\n" +
        "  TUCK <= IF FALSE EXIT THEN\n" +
        "  TRUE\n" +
        ";\n";

        /// <summary>
        /// Fixups:
        /// 
        /// 1) Define alias for KEY.
        /// </summary>
        [WordName("INKEY")]
        [WordSet(WordSets.LEGACY)]
        [Depends("KEY")]
        [Syntax("( -- c )")]
        internal static String INKEY = ": INKEY KEY ;\n";

        /// <summary>
        /// Variable for DO LOOP
        /// </summary>
        [WordName("LEAVE-SP")]
        [WordSet(WordSets.LEGACY)]
        [Depends("CELLS")]
        [Depends("ALLOT")]
        [Depends("!")]
        [Syntax("( -- )")]
        internal static String LEAVE_SP = 
            "CREATE LEAVE-SP 32 CELLS ALLOT\n" +
            "LEAVE-SP LEAVE-SP !\n";

        /// <summary>
        /// 3200 - Standard words for booleans
        /// </summary>
        [WordName("NOT")]
        [WordSet(WordSets.LEGACY)]
        [Depends("0=")]
        [Syntax("( -- )")]
        internal static String NOT = ": NOT 0= ;\n";

        /// <summary>
        /// 
        /// </summary>
        [WordName("RESOLVE-DO")]
        [WordSet(WordSets.LEGACY)]
        [Depends("(")]
        [Depends("IF")]
        [Depends("IF")]
        [Depends("DUP")]
        [Depends("HERE")]
        [Depends("-")]
        [Depends("CELLS")]
        [Depends("OVER")]
        [Depends("SWAP")]
        [Depends("!")]
        [Depends("ELSE")]
        [Depends(",")]
        [Depends("THEN")]
        [Syntax("( here 0|1 -- here )")]
        internal static String RESOLVE_DO = 
        "(\n" +
        "  RESOLVE-DO Back fill offset of ?DO or DO depending whether top of stack is 1 or 0.\n" +
        ")\n" +
        ": RESOLVE-DO ( here 0|1 -- here )         \n" +
        "    IF ( ?DO )                            \n" +
        "        DUP HERE - ,                      \n" +
        "        DUP 2 CELLS - HERE OVER - SWAP !  \n" +
        "    ELSE ( DO )                           \n" +
        "        DUP HERE - ,                      \n" +
        "    THEN                                  \n" +
        ";\n";

        /// <summary>
        /// 
        /// </summary>
        [WordName("RESOLVE-LEAVES")]
        [WordSet(WordSets.LEGACY)]
        [Depends("(")]
        [Depends("BEGIN")]
        [Depends("LEAVE-SP")]
        [Depends("@")]
        [Depends("OVER")]
        [Depends(">")]
        [Depends("AND")]
        [Depends("WHILE")]
        [Depends("HERE")]
        [Depends("-")]
        [Depends("!")]
        [Depends("CELLS")]
        [Depends("NEGATE")]
        [Depends("+!")]
        [Depends("REPEAT")]
        [Depends("DROP")]
        [Syntax("RESOLVE-LEAVES ( here -- )")]
        internal static String RESOLVE_LEAVES = 
        ": RESOLVE-LEAVES ( here - )         \n" +
        "    BEGIN                           \n" +
        "        LEAVE-SP @ @ OVER >         \n" +
        "        LEAVE-SP @ LEAVE-SP > AND   \n" +
        "    WHILE                           \n" +
        "        HERE LEAVE-SP @ @ - LEAVE-SP @ @ !  \n" +
        "        1 CELLS NEGATE LEAVE-SP +!          \n" +
        "    REPEAT                          \n" +
        "    DROP                            \n" +
        ";\n";

        /// <summary>
        /// 
        /// </summary>
        [WordName("TELL")]
        [WordSet(WordSets.LEGACY)]
        [Depends("(")]
        [Depends("TYPE")]
        [Syntax("( c-addr u -- )")]
        internal static String TELL = ": TELL ( c-addr u -- ) TYPE ;\n";

        /// <summary>
        /// 3362 - UNLESS is the same as IF but the test is reversed.
        /// </summary>
        [WordName("UNLESS")]
        [WordSet(WordSets.LEGACY)]
        [Depends("IMMEDIATE")]
        [Depends("[']")]
        [Depends("NOT")]
        [Depends("[COMPILE]")]
        [Depends("IF")]
        [Syntax("( -- )")]
        internal static String UNLESS = ": UNLESS IMMEDIATE ['] NOT , [COMPILE] IF ;\n";

        /// <summary>
        /// (3479) .S is implemented in C#.
        /// </summary>
        [WordName("UWIDTH")]
        [WordSet(WordSets.LEGACY)]
        [Depends("(")]
        [Depends("BASE")]
        [Depends("@")]
        [Depends("/")]
        [Depends("?DUP")]
        [Depends("IF")]
        [Depends("RECURSE")]
        [Depends("1+")]
        [Depends("ELSE")]
        [Depends("THEN")]
        [Syntax("( u -- width )")]
        internal static String U_WIDTH = 
            "  ( This word returns the width (in characters) of an unsigned number in the current base )\n" +
            ": UWIDTH                   ( u -- width )\n" +
            "    BASE @ /               ( rem quot )\n" +
            "    ?DUP IF                ( if quotient <> 0 then )\n" +
            "        RECURSE 1+         ( return 1+recursive call )\n" +
            "    ELSE\n" +
            "        1                  ( return 1 )\n" +
            "    THEN\n" +
            ";\n";

        #endregion Fields
    }
}